<!--
 * @Author: 大话主席 superslide2.com
 * @Description: js-多边形各种算法
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>js多边形各种算法-大话主席 superslide2.com</title>
  </head>
  <!-- 核心算法都在 utils.js 里面-->
  <script src="utils.js"></script>
  <body>
    <div class="wrap">
      <h1>js多边形各种算法-大话主席 superslide2.com</h1>
      <div class="canvas-wrap">
        <canvas id="canvas"></canvas>
      </div>
      <div id="tip">信息提示</div>
      <div class="btns">
        <button id="btnZoomOut" class="green">缩小多边形</button>
        <button id="btnZoomIn" class="blue">放大多边形</button>
        <button id="btnGetCenter" class="red">获取中心</button>
        <button id="btnGetBaryCenter" class="black">获取重心（质心）</button>
        <button id="reset">重置</button>
      </div>
    </div>

    <script>
      const canvasWidth = 800; // canvas宽
      const canvasHeight = 500; // canvas高
      const canvasEle = document.querySelector("#canvas");
      const tipEle = document.querySelector("#tip");
      const ctx = canvasEle.getContext("2d");

      canvasEle.width = canvasWidth;
      canvasEle.height = canvasHeight;

      const polygons = [
        // 随机多边形坐标点
        [
          { x: 116, y: 75 },
          { x: 137, y: 15 },
          { x: 156, y: 80 },
          { x: 234, y: 80 },
          { x: 181, y: 133 },
          { x: 214, y: 186 },
          { x: 127, y: 154 },
          { x: 45, y: 201 },
          { x: 68, y: 140 },
          { x: 16, y: 71 },
        ],
        [
          { x: 314, y: 61 },
          { x: 385, y: 128 },
          { x: 496, y: 35 },
          { x: 390, y: 182 },
        ],
        [
          { x: 549, y: 57 },
          { x: 625, y: 93 },
          { x: 657, y: 13 },
          { x: 687, y: 83 },
          { x: 754, y: 41 },
          { x: 759, y: 106 },
          { x: 697, y: 130 },
          { x: 715, y: 175 },
          { x: 664, y: 192 },
          { x: 640, y: 147 },
          { x: 562, y: 162 },
        ],
        // 凹多边形坐标点
        [
          { x: 50, y: 400 },
          { x: 50, y: 280 },
          { x: 80, y: 280 },
          { x: 80, y: 370 },
          { x: 180, y: 370 },
          { x: 180, y: 280 },
          { x: 210, y: 280 },
          { x: 210, y: 400 },
        ],
        // 凸多边形坐标点
        [
          { x: 300, y: 400 },
          { x: 300, y: 370 },
          { x: 390, y: 370 },
          { x: 390, y: 260 },
          { x: 420, y: 260 },
          { x: 420, y: 370 },
          { x: 510, y: 370 },
          { x: 510, y: 400 },
        ],
        // 正方形
        [
          { x: 620, y: 280 },
          { x: 740, y: 280 },
          { x: 740, y: 390 },
          { x: 620, y: 390 },
        ],
      ];

      // 初始化
      function init() {
        drawPolygons();
        drawPolygonsName();
      }
      init();

      // 绘制所有多边形
      function drawPolygons() {
        polygons.forEach((polygon) => {
          drawPolygon(polygon);
        });
      }

      // 绘制所有多边形-名称
      function drawPolygonsName() {
        polygons.forEach((polygon, index) => {
          drawPolygonName(polygon, index);
        });
      }

      // 绘制所有多边形-中心点
      function drawPolygonsCenter() {
        polygons.forEach((polygon) => {
          drawPolygonCenter(polygon);
        });
      }

      // 绘制所有多边形-重心（质心）
      function drawPolygonsBaryCenter() {
        polygons.forEach((polygon) => {
          drawPolygonBaryCenter(polygon);
        });
      }

      // 绘制所有多边形-放大
      function drawZoomInPolygons() {
        polygons.forEach((polygon) => {
          drawZoomInPolygon(polygon);
        });
      }

      // 绘制所有多边形-放大
      function drawZoomOutPolygons() {
        polygons.forEach((polygon) => {
          drawZoomOutPolygon(polygon);
        });
      }

      // 绘制多边形中心点方法
      function drawPolygonCenter(points) {
        ctx.beginPath();
        ctx.fillStyle = "rgba(255,0,0,.5)";
        const p = getPolygonCenter(points);
        ctx.arc(p.x, p.y, 5, 0, 2 * Math.PI);
        ctx.closePath();
        ctx.fill();
      }

      // 绘制多边形重心（质心）方法
      function drawPolygonBaryCenter(points) {
        ctx.beginPath();
        ctx.fillStyle = "rgba(0,0,0,.5)";
        const p = getPolygonBaryCenter(points);
        ctx.arc(p.x, p.y, 5, 0, 2 * Math.PI);
        ctx.closePath();
        ctx.fill();
      }

      // 绘制多边形方法
      function drawPolygon(points, strokeStyle) {
        ctx.beginPath();
        ctx.lineWidth = "1";
        ctx.strokeStyle = strokeStyle || "#f00";

        points.forEach((p, i) => {
          if (i === 0) {
            ctx.moveTo(p.x, p.y);
          } else {
            ctx.lineTo(p.x, p.y);
          }
        });

        ctx.closePath();
        ctx.stroke();
      }

      // 绘制多边形方法-名称
      function drawPolygonName(points, index) {
        const center = getPolygonCenter(points);
        ctx.fillStyle = "#f00";
        ctx.font = "20px Arial";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText(index, center.x, center.y + 100);
      }

      // 绘制多边形方法-放大
      function drawZoomInPolygon(points) {
        const zoomInPoints = scalePolygon(points, 5);
        drawPolygon(zoomInPoints, "#00f");
      }

      // 绘制多边形方法-缩小
      function drawZoomOutPolygon(points) {
        const zoomOutPoints = scalePolygon(points, -5);
        drawPolygon(zoomOutPoints, "#0f0");
      }

      /** 事件绑定 */
      // 缩小多边形
      document.querySelector("#btnZoomOut").onclick = function () {
        drawZoomOutPolygons();
      };

      // 放大多边形
      document.querySelector("#btnZoomIn").onclick = function () {
        drawZoomInPolygons();
      };

      // 获取中心
      document.querySelector("#btnGetCenter").onclick = function () {
        drawPolygonsCenter();
      };

      // 获取重心（质心）
      document.querySelector("#btnGetBaryCenter").onclick = function () {
        drawPolygonsBaryCenter();
      };

      // 重置
      document.querySelector("#reset").onclick = function () {
        canvasEle.width = canvasWidth;
        init();
      };

      // canvas获取坐标并判断在那个多边形内
      // const clickPoints = [];
      canvasEle.onclick = function (e) {
        // 获取点击坐标
        const p = {
          x: e.clientX - canvasEle.offsetLeft,
          y: e.clientY - canvasEle.offsetTop,
        };

        tipEle.innerHTML = `点击坐标：${p.x},${p.y}`;

        // 判断坐标在那个多边形内
        let polygonIndex = -1;
        for (let i = 0; i < polygons.length; i++) {
          const polygon = polygons[i];
          polygonIndex = isInPolygon(p, polygon) ? i : -1;
          if (polygonIndex !== -1) break;
        }
        tipEle.innerHTML +=
          polygonIndex !== -1
            ? `，<strong>该坐标在多边形[${polygonIndex}]内</strong>`
            : "";

        // clickPoints.push(p);
        // console.log(`点击坐标集合：${JSON.stringify(clickPoints)}`);
      };
    </script>

    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        background: #f2f2f2;
        text-align: center;
        font-size: 14px;
      }
      h1 {
        margin: 30px 0;
      }
      .canvas-wrap {
        width: 800px;
        height: 500px;
        margin: 20px auto;
        background: #fff;
      }
      #canvas {
        width: 100%;
        height: 100%;
      }
      #tip strong {
        color: #f00;
      }
      .btns button {
        margin: 20px 10px;
        padding: 12px 0;
        width: 130px;
        cursor: pointer;
        color: #fff;
        border-radius: 5px;
        border: 0;
        background: #ccc;
      }
      .btns .green {
        background: #0f0;
      }
      .btns .blue {
        background: #00f;
      }
      .btns .red {
        background: #f00;
      }
      .btns .black {
        background: #000;
      }
    </style>
  </body>
</html>
